<template>
  <div class="json-editor">
    <div class="editor-header">
      <h3>视图编辑器</h3>
      <div class="actions">
        <el-button @click="formatJson" type="primary" size="small">格式化</el-button>
      </div>
    </div>

    <div class="editor-container">
      <div ref="editorContainer" class="monaco-editor" :class="{ 'editor-error': !isValid }"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, onMounted, onUnmounted, nextTick } from 'vue'
import loader from '@monaco-editor/loader'
import type * as monaco from 'monaco-editor'
import { ListSchema } from '@/type/common/list-schema'
import { InfoSchema } from '@/type/common/info-schema'

interface JsonEditorProps {
  modelValue?: string
  schema: any
}

const props = withDefaults(defineProps<JsonEditorProps>(), {
  modelValue: '',
  schema: {}
})

const emit = defineEmits<{
  'update:modelValue': [value: string]
  change: [value: string, isValid: boolean]
}>()

const editorContainer = ref<HTMLElement>()
let editor: monaco.editor.IStandaloneCodeEditor | null = null

const jsonText = ref(props.modelValue)
const errorMessage = ref('')
const isValid = ref(true)
const lineCount = ref(1)

// 配置 Monaco Editor
const configureMonaco = (monacoInstance: typeof monaco) => {
  // 设置 JSON 语言配置
  monacoInstance.languages.json.jsonDefaults.setDiagnosticsOptions({
    validate: true,
    allowComments: false,
    schemas: [
      {
        uri: 'https://example.com/mate-config-schema.json', // 这个 URI 可以任意，但要唯一
        fileMatch: ['*'], // 匹配所有 JSON 文件
        schema: props.schemaType === 'List' ? ListSchema : InfoSchema
      }
    ]
  })
}

// 初始化编辑器
const initEditor = async () => {
  if (!editorContainer.value) return

  try {
    // 使用 @monaco-editor/loader 加载 Monaco Editor
    const monacoInstance = await loader.init()

    // 配置 Monaco
    configureMonaco(monacoInstance)

    // 格式化初始值
    const initialValue = formatJsonValue(jsonText.value)

    // 创建编辑器
    editor = monacoInstance.editor.create(editorContainer.value, {
      value: initialValue,
      language: 'json',
      theme: 'vs',
      automaticLayout: true,
      fontSize: 14,
      lineNumbers: 'on',
      roundedSelection: true,
      scrollBeyondLastLine: false,
      readOnly: false,
      wordWrap: 'on',
      minimap: { enabled: false },
      tabSize: 2,
      insertSpaces: true,
      detectIndentation: true,
      folding: true,
      showFoldingControls: 'mouseover'
    })

    // 监听内容变化
    editor.onDidChangeModelContent(() => {
      const value = editor?.getValue() || ''
      jsonText.value = value
      updateLineCount()
      validateJson()
      emit('update:modelValue', value)
      emit('change', value, isValid.value)
    })

    // 监听验证标记变化
    const disposable = monacoInstance.editor.onDidChangeMarkers(() => {
      const model = editor?.getModel()
      if (model) {
        const markers = monacoInstance.editor.getModelMarkers({ resource: model.uri })
        const hasErrors = markers.some(
          (marker: any) => marker.severity === monacoInstance.MarkerSeverity.Error
        )

        if (hasErrors) {
          const errorMarker = markers.find(
            (marker: any) => marker.severity === monacoInstance.MarkerSeverity.Error
          )
          errorMessage.value = errorMarker?.message || 'JSON 格式错误'
          isValid.value = false
        } else {
          errorMessage.value = ''
          isValid.value = true
        }
      }
    })

    // 清理函数
    onUnmounted(() => {
      disposable.dispose()
      editor?.dispose()
    })
  } catch (error) {
    console.error('Failed to load Monaco Editor:', error)
    // 如果 Monaco Editor 加载失败，回退到 textarea
    fallbackToTextarea()
  }
}

// 回退到 textarea 编辑器
const fallbackToTextarea = () => {
  if (!editorContainer.value) return

  const textarea = document.createElement('textarea')
  textarea.className = 'fallback-textarea'
  textarea.value = formatJsonValue(jsonText.value)
  textarea.placeholder = '请输入 JSON 数据...'
  textarea.spellcheck = false
  textarea.style.cssText = `
    width: 100%;
    height: 100%;
    border: none;
    outline: none;
    resize: none;
    font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
    font-size: 14px;
    line-height: 1.5;
    padding: 8px;
    color: #333;
    background-color: #fff;
  `

  textarea.addEventListener('input', () => {
    jsonText.value = textarea.value
    updateLineCount()
    validateJson()
    emit('update:modelValue', textarea.value)
    emit('change', textarea.value, isValid.value)
  })

  editorContainer.value.innerHTML = ''
  editorContainer.value.appendChild(textarea)
}

// 计算行数
const updateLineCount = () => {
  lineCount.value = jsonText.value.split('\n').length
}

// 验证 JSON
const validateJson = () => {
  if (!jsonText.value.trim()) {
    isValid.value = true
    errorMessage.value = ''
    return
  }

  try {
    JSON.parse(jsonText.value)
    isValid.value = true
    errorMessage.value = ''
  } catch (error) {
    isValid.value = false
    errorMessage.value = `JSON 解析错误: ${(error as Error).message}`
  }
}

// 格式化 JSON 值
const formatJsonValue = (value: string): string => {
  if (!value.trim()) return value
  try {
    const parsed = JSON.parse(value)
    return JSON.stringify(parsed, null, 2)
  } catch (error) {
    // 如果解析失败，返回原始值
    return value
  }
}

// 格式化 JSON
const formatJson = () => {
  if (!jsonText.value.trim()) return
  try {
    const formatted = formatJsonValue(jsonText.value)
    if (editor) {
      editor.setValue(formatted)
    } else {
      jsonText.value = formatted
    }
    isValid.value = true
    errorMessage.value = ''
    updateLineCount()
  } catch (error) {
    isValid.value = false
    errorMessage.value = `JSON 解析错误: ${(error as Error).message}`
  }
}

// 清空 JSON
const clearJson = () => {
  if (editor) {
    editor.setValue('')
  } else {
    jsonText.value = ''
  }
  isValid.value = true
  errorMessage.value = ''
  updateLineCount()
}

// 监听 props 变化
watch(
  () => props.modelValue,
  (newValue, oldValue) => {
    if (newValue !== jsonText.value) {
      const formattedValue = formatJsonValue(newValue)
      if (editor && editor.setValue) {
        editor.setValue(formattedValue)
      } else {
        jsonText.value = formattedValue
      }
      updateLineCount()
      validateJson()
    }
  }
)

// 初始化
onMounted(() => {
  nextTick(() => {
    initEditor()
    updateLineCount()
    validateJson()
  })
})
</script>

<style scoped>
.json-editor {
  height: 100%;
  display: flex;
  flex-direction: column;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  overflow: hidden;
}

.editor-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 16px;
  background-color: #f5f7fa;
  border-bottom: 1px solid #dcdfe6;
}

.editor-header h3 {
  margin: 0;
  color: #303133;
  font-size: 16px;
}

.actions {
  display: flex;
  gap: 8px;
}

.editor-container {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.monaco-editor {
  flex: 1;
  min-height: 400px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.monaco-editor.editor-error {
  border-color: #f56c6c;
  box-shadow: 0 0 0 1px #f56c6c;
}

.editor-status {
  padding: 8px 16px;
  background-color: #f5f7fa;
  border-top: 1px solid #dcdfe6;
  min-height: 40px;
}

.status-info {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 4px;
}

.status-valid {
  color: #67c23a;
  font-weight: 500;
}

.status-invalid {
  color: #f56c6c;
  font-weight: 500;
}

.line-count {
  color: #909399;
  font-size: 12px;
}

.error-message {
  color: #f56c6c;
  font-size: 12px;
  background-color: #fef0f0;
  padding: 4px 8px;
  border-radius: 2px;
  border-left: 3px solid #f56c6c;
}

.schema-hints {
  border-top: 1px solid #dcdfe6;
  max-height: 200px;
  overflow: auto;
}

.schema-hints h4 {
  margin: 0;
  padding: 12px 16px;
  background-color: #f0f9ff;
  color: #409eff;
  font-size: 14px;
  border-bottom: 1px solid #dcdfe6;
}

.hint-content {
  padding: 12px 16px;
}

.hint-example {
  margin: 0;
  font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
  font-size: 12px;
  line-height: 1.4;
  color: #606266;
  background-color: #f8f9fa;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #e4e7ed;
  overflow-x: auto;
  white-space: pre-wrap;
}

/* 回退 textarea 样式 */
.fallback-textarea:focus {
  background-color: #fafafa;
}
</style>
